#pragma once
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <memory>
#include "MemoryFileSystem.hpp"

// BUILDER BY ZERO123
namespace QAddon
{
	class Builder;

	enum BUILD_STATE
	{
		SUCCESS,
		ERROR,
	};

	// 构建上下文数据 用于传递给Task
	class BuildContext
	{
	public:
		// 有限可访问的Path目录 可能为nullptr
		QMFS::Path* buildPath;
		// 输出PACKAGE目录
		QMFS::Path* behFS;
		QMFS::Path* resFS;
		Builder* parent;
		BuildContext(QMFS::Path* buildPath, QMFS::Path* behFS, QMFS::Path* resFS, Builder* parent):
			buildPath(buildPath), behFS(behFS), resFS(resFS), parent(parent) {}

		QMFS::Path* mallocModDir();
	};

	// 构建Task
	class BuildTask
	{
	public:
		// 构造开始时触发
		BuildTask() {}
		virtual std::string getRefPath()
		{
			return "";
		}
		virtual void onBuild(Builder*, BuildContext*) = 0;
		virtual ~BuildTask() {};
	};

	// Builder构建器
	class Builder
	{
	protected:
		// 虚拟文件系统表 每个物理目录至多解析一次
		QMFS::Path mfMap;
		// 待处理Task任务表
		std::vector<std::shared_ptr<BuildTask>> buildTasks;
		bool errorState = false;
		// 统计已经加载过的物理目录 避免重复读取数据
		std::unordered_set<std::string> phyPathLoadSet;

		// 加载物理文件目录
		virtual QMFS::Path& loadPhyPath(const std::string& absPhyPath, const std::string& mPath)
		{
			if (phyPath.empty())
			{
				return mfMap.createPath(mPath);
			}
			// 存在物理目录绑定时
			auto& mPathData = mfMap.createPath(mPath);
			std::string realPath = QMFS::pathLexicallyNormal(mPath, true);
			if (phyPathLoadSet.find(realPath) == phyPathLoadSet.end())
			{
				// 防止重复解析相同的物理目录
				QMFS::Path::loadPhyPathToMFS(&mPathData, phyPath / absPhyPath);
				phyPathLoadSet.insert(realPath);
			}
			return mPathData;
		}

	public:
		// 行为/资源包文件系统
		QMFS::Path behFS;
		QMFS::Path resFS;
		// 全局环境变量
		std::unordered_map<std::string, std::string> globalEnv;
		// 编译单元的物理路径
		const std::filesystem::path phyPath;

		Builder() noexcept {}
		Builder(const std::filesystem::path& bindPhyPath): phyPath(bindPhyPath){}
		Builder(std::filesystem::path&& bindPhyPath) noexcept : phyPath(std::move(bindPhyPath)) {};

		virtual ~Builder() {}

		// 分配Mod目录
		virtual QMFS::Path* mallocModDir()
		{
			return &behFS.createPath("unknowMod");
		}

		// 获取环境变量 若不存在返回空字符串
		std::string getEnv(const std::string& envKey, const std::string& defaultValue = "") const
		{
			if (globalEnv.find(envKey) != globalEnv.end())
			{
				return globalEnv.at(envKey);
			}
			return defaultValue;
		}

		// 字符串变量置换(根据当前上下文)
		std::string replVarRefs(const std::string& txt) const
		{
			return optimizedReplace(txt, globalEnv);
		}

		// 设置环境变量
		void setEnv(const std::string& key, const std::string& value)
		{
			globalEnv[key] = value;
		}

		// 添加编译任务
		void addTask(std::shared_ptr<BuildTask> task)
		{
			buildTasks.push_back(task);
		}

		virtual void buildBefore()
		{
			// 清理历史垃圾
			mfMap.removeChildDirs();
			behFS.removeChildDirs();
			resFS.removeChildDirs();
			// 生成网易依赖的特定识别目录
			behFS.createPath("entities", true);
			resFS.createPath("textures", true);
		}

		// 开始构建工作
		virtual BUILD_STATE build()
		{
			errorState = false;
			buildBefore();
			for (auto& task : buildTasks)
			{
				auto refPath = task->getRefPath();
				BuildContext context{
					refPath.empty() ? nullptr : &loadPhyPath(refPath, refPath), &behFS, &resFS, this
				};
				task->onBuild(this, &context);
				if (this->errorState)
				{
					return BUILD_STATE::ERROR;
				}
			}
			return BUILD_STATE::SUCCESS;
		}

		// 获取系统时间
		static std::string getCurrentTime()
		{
			// 获取当前时间点
			auto now = std::chrono::system_clock::now();
			// 转换为time_t类型以便格式化
			std::time_t time_now = std::chrono::system_clock::to_time_t(now);

			// 使用 localtime_s 获取本地时间
			std::tm local_time;
			localtime_s(&local_time, &time_now);  // 传入tm结构体指针和time_t

			std::ostringstream oss;
			oss << std::put_time(&local_time, "[%H:%M:%S]");
			return oss.str();
		}

		// 格式化LOG字段 将为字段添加时间轴
		static std::string formatLog(const std::string& log, const std::string& logHead="")
		{
			std::string newLog = getCurrentTime();
			newLog.push_back(' ');
			if (!logHead.empty())
			{
				newLog.append(logHead);
				newLog.push_back(' ');
			}
			newLog.append(log);
			return newLog;
		}

		// 常规日志输出
		virtual void logInfo(const std::string& log) const
		{
			std::cout << formatLog(log, "[INFO]") << "\n";
		}

		// 成功日志输出
		virtual void logSuccess(const std::string& log) const
		{
			std::cout << "\033[32;1m" << formatLog(log, "[SUCCESS]") << "\033[0m\n";
		}

		// 错误输出
		virtual void logError(const std::string& log) const
		{
			std::cout << "\033[31;1m" << formatLog(log, "[ERROR]") << "\033[0m\n";
		}

		// 抛出并终止编译工作
		virtual void logErrorThrow(const std::string& log)
		{
			errorState = true;
			std::cout << "\033[31;1m" << formatLog(log, "[严重性][ERROR]") << "\033[0m\n";
		}

		// 警告型日志输出
		virtual void logWarning(const std::string& log) const
		{
			std::cout << "\033[33;1m" << formatLog(log, "[WARNING]") << "\033[0m\n";
		}
	};

	QMFS::Path* BuildContext::mallocModDir()
	{
		return parent->mallocModDir();
	}
}